
#include "capabilities.h"
#include "ldac_dec_priv_lib.h"
#include "a2dp_decode/a2dp_common_decode.h"
#ifndef LIB_PKG
#include "debug.h"
#endif
#include "patch/patch.h"
/***************************************************************************
Private Function Declarations
*/
void HandleInputBufferMetadata(LDAC_DEC_PARAMS *pDecParams, tCbuffer *in_buffer, int read_octets, tCbuffer *metadata_op_buffer);




void reset_cbuffers( tCbuffer *cb )
{
    // reset cbuffer read/write pointer
    unsigned int *addr = (unsigned int*)cb->base_addr;
    cbuffer_set_read_address_ex(cb, addr, 0u);
    cbuffer_set_write_address_ex(cb, addr, 0u);
}


static void bc_swap_endian_int32( unsigned char *p ){
    unsigned char uc0, uc1, uc2, uc3;
    uc0 = p[0];  uc1 = p[1];  uc2 = p[2];  uc3 = p[3];
    p[0] = uc3;  p[1] = uc2;  p[2] = uc1;  p[3] = uc0;
}

static unsigned bc_read_ldac_frame_header( unsigned char *p_stream,
                                           int *sampling_rate_index, int *channel_config_index,
                                           int *frame_length_index, int *frame_status )
{
    /*---------------------------------------------------*/
    /* | p_stream[0]   | p_stream[1]   | p_stream[2]   | */
    /* |0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7| */
    /* | A             |  B  | C |  D              | E | */
    /*---------------------------------------------------*/
    /*    A: 8bit : syncword                             */
    /*    B: 3bit : sampling_rate_index                  */
    /*    C: 2bit : channel_config_index                 */
    /*    D: 9bit : frame_length_index                   */
    /*    E: 2bit : frame_status                         */
    /*---------------------------------------------------*/
    if( p_stream[0] != 0xAA ){
        L2_DBG_MSG3("LDAC bc_read_ldac_frame_header : worng syncword! [%x|%x|%x]", p_stream[0],p_stream[1],p_stream[2]);
        return CODEC_ERROR;
    }
    *sampling_rate_index = (p_stream[1] >> 5) & 0x7;
    *channel_config_index =  (p_stream[1] >> 3) & 0x3;
    *frame_length_index = p_stream[1] << 8 | p_stream[2];
    *frame_length_index >>= 2;
    *frame_length_index &= 0x000001FF;
    
    *frame_status = p_stream[2];
    *frame_status &= 0x00000003;
    return CODEC_SUCCESS;
}

static unsigned bc_get_ldac_frame_size( tCbuffer *cb_buf, tCbuffer *cb_work, int *p_read_bytes, int *pframe_size, int *pframe_status )
{
    unsigned int *addr, offset;
    unsigned char *p_stream, a_head[3];
    int sampling_rate_index, channel_config_index, frame_length_index;
    *pframe_size = 0;
    *pframe_status = 0;
    /* read only config data (4byte aligned) */
    reset_cbuffers(cb_work); // reset
    *p_read_bytes = cbuffer_copy_ex(cb_work, cb_buf, 4);

    if(*p_read_bytes < 4){
          L2_DBG_MSG1("bc_get_ldac_frame_size() : Not Enough Input DATA. n_read_bytes=%d",*p_read_bytes);
        return CODEC_NOT_ENOUGH_INPUT_DATA;
    }
    addr = cbuffer_get_read_address_ex(cb_work, &offset); // offset may be allways 0
    p_stream = (unsigned char*)(addr + offset);
    a_head[0] = p_stream[3];
    a_head[1] = p_stream[2];
    a_head[2] = p_stream[1];

    if( CODEC_ERROR == bc_read_ldac_frame_header(a_head, &sampling_rate_index, &channel_config_index,
                                                   &frame_length_index, pframe_status)){
        return CODEC_ERROR;
    }
    *pframe_size = frame_length_index + 4;

    return CODEC_SUCCESS;
}


static void rxbuf_op_sync_clone( LDAC_DEC_RX_BUF *hRxBuf )
{
    unsigned *addr, offset;
    addr = cbuffer_get_read_address_ex(hRxBuf->main, &offset);
    cbuffer_set_read_address_ex(hRxBuf->clone, addr, offset);
    addr = cbuffer_get_write_address_ex(hRxBuf->main, &offset);
    cbuffer_set_write_address_ex(hRxBuf->clone, addr, offset);
}

static void rxbuf_op_discard_data( LDAC_DEC_RX_BUF *hRxBuf, int bytes )
{
    /* advance read pointer and sync with clone */
    cbuffer_advance_read_ptr_ex(hRxBuf->main, bytes);
    rxbuf_op_sync_clone(hRxBuf);
}

static int check_fs(int fs_id,int sampling_freq)
{
    if(fs_id == 0x03){
        if(sampling_freq==96000){
            //fs OK
            return 1;
        }else{
            return 0;
        }
    }else if(fs_id == 0x02){
        if(sampling_freq==88200){
            //fs OK
            return 1;
        }else{
            return 0;
        }
    }else if(fs_id == 0x01){
        if(sampling_freq==48000){
            //fs OK
            return 1;
        }else{
            return 0;
        }
    }else if(fs_id == 0x00){
        if(sampling_freq==44100){
            //fs OK
            return 1;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
}

static int check_ch(int ch_id,int channel_mode)
{
    if(ch_id == 0x00){//mono
        if(channel_mode==0x04){
            //ch OK
            return 1;
        }else{
            return 0;
        }
    }else if(ch_id == 0x01){//dual
        if(channel_mode==0x02){
            //ch OK
            return 1;
        }else{
            return 0;
        }
    }else if(ch_id == 0x02){//stereo
        if(channel_mode==0x01){
            //ch OK
            return 1;
        }else{
            return 0;
        }
    }else{
        return 0;
    }
}

static unsigned search_next_frame_header( LDAC_DEC_RX_BUF *hRxBuf, tCbuffer *cb_out,int frame_size,int sampling_freq,int channel_mode )
{
    int p_read_bytes,i;
    unsigned char fs_id,ch_id;
    unsigned *addr,*addr1, offset;
    unsigned char *p_stream, a_head[4];
    tCbuffer *cb_buf,*cb_work;
    int flag_aa;
    int total_skip_size;
    
    total_skip_size=0;
    cb_buf = hRxBuf->clone;
    cb_work = cb_out;
    flag_aa=0;
    
    for(;;){
        reset_cbuffers(cb_work); // reset
        addr1 = cbuffer_get_read_address_ex(cb_buf, &offset); // offset may be allways 0
        p_read_bytes = cbuffer_copy_ex(cb_work, cb_buf, 4);
        if(p_read_bytes < 4){
            L2_DBG_MSG1("search_next_frame_header() : Not Enough Input DATA. n_read_bytes=%d",p_read_bytes);
            return CODEC_NOT_ENOUGH_INPUT_DATA;
        }
        addr = cbuffer_get_read_address_ex(cb_work, &offset); // offset may be allways 0
        p_stream = (unsigned char*)(addr + offset);
        a_head[0] = p_stream[3];
        a_head[1] = p_stream[2];
        a_head[2] = p_stream[1];
        a_head[3] = p_stream[0];
        for(i=0;i<4;i++){
            if(!flag_aa){
                if(a_head[i] == 0xAA){
                    if(i < 3 ){
                        //fs check
                        fs_id = (a_head[i+1] & 0xE0)>>5;
                        if(check_fs(fs_id,sampling_freq)){
                            ch_id = (a_head[i+1] & 0x18)>>3;
                            if(check_ch(ch_id,channel_mode)){
                                goto FRAME_FOUND;
                            }
                        }
                    }else{
                        flag_aa=1;
                    }
                }
            }else{
                //found 0xAA previous buffer.
                //fs check
                fs_id = (a_head[i] & 0xE0)>>5;
                if(check_fs(fs_id,sampling_freq)){
                    ch_id = (a_head[i] & 0x18)>>3;
                    if(check_ch(ch_id,channel_mode)){
                        goto FRAME_FOUND;
                    }
                }
                flag_aa=0;
            }
        }
        cbuffer_set_read_address_ex(cb_buf,addr1+1,offset);
        total_skip_size+=4;
        if((total_skip_size > frame_size)&&(frame_size)){
            hRxBuf->nFrame--;
        }
    }
FRAME_FOUND:    
    //found sync data
    if(!flag_aa){
        offset +=i; 
        cbuffer_set_read_address_ex(cb_buf,addr1,offset);
    }else{
        offset +=3; 
        cbuffer_set_read_address_ex(cb_buf,addr1-1,offset);
    }
    return CODEC_SUCCESS;
}

static unsigned rxbuf_op_peek_frame_data( LDAC_DEC_RX_BUF *hRxBuf, tCbuffer *cb_out,
                                          int *n_read_bytes, uint32 *status)
{
    int size, ii;
    int sts;
    unsigned *addr, offset;
    unsigned char *p_stream;
    unsigned mode = bc_get_ldac_frame_size( hRxBuf->clone, cb_out, n_read_bytes, &size, &sts);
    if( mode != CODEC_SUCCESS ) {
        return mode;
    }

    /* frame status */
    *status = sts;

    /* read stream data */
    *n_read_bytes += cbuffer_copy_ex(cb_out, hRxBuf->clone, (size-*n_read_bytes));
    if(*n_read_bytes != size ){
        return CODEC_NOT_ENOUGH_INPUT_DATA;
    }
    addr = cbuffer_get_read_address_ex(cb_out, &offset);
    p_stream = (unsigned char*)(addr + offset);
    /* swap endian */
    /* [ii+n] can be get bigger than n_read_bytes, so please make sure that the size of a_tream[] is big enough. */
    for (ii = 0; ii<*n_read_bytes; ii+=4) {
        bc_swap_endian_int32( &p_stream[ii] );
    }
    return CODEC_SUCCESS;
}

static void rxbuf_op_pop_frame_data( LDAC_DEC_RX_BUF *hRxBuf, int frame_bytes )
{
    rxbuf_op_discard_data(hRxBuf, frame_bytes);
    if( (hRxBuf->nFrame--) < 0 ){ hRxBuf->nFrame = 0; }
}



int ldac_decoder_enough_frames_to_decode( LDAC_DEC_PARAMS *pDecParams )
{
    // when playing has not started, await 64 frames of audio to be stored before allowing playback to commence
    if( pDecParams->playing != TRUE )
    {
        if( pDecParams->RxBuf.nFrame < DECODER_NUM_FRAMES_STARTS_DECODE ){// 64: to be changed to the paramer of LDAC_DEC_PARAMS.
            L2_DBG_MSG1("LDAC ldac_decoder_enough_frames_to_decode frames=%d ",pDecParams->RxBuf.nFrame);
            return 0; // return 0 because not ready to start playback
        }
        // initialize to start decoding
        pDecParams->playing=TRUE;
    }

    // number of available frames of data
    return pDecParams->RxBuf.nFrame;
}

int ldac_decoder_stores_rx_data(tCbuffer *in_buffer, LDAC_DEC_PARAMS *pDecParams, int *nFrmRegistered)
{
    int nFrmRx, rx_octets, read_octets, space_octets, payload_header;
    unsigned int *addr, offset, nsft;
    LDAC_DEC_RX_BUF *hRxBuf = &pDecParams->RxBuf;
    tCbuffer *cb_main = hRxBuf->main;
    tCbuffer *cb_work = pDecParams->cb_stream;
    //tCbuffer *cb_clone = hRxBuf->clone;

    *nFrmRegistered = 0;
    read_octets = 0;
    unsigned b4idx, afteridx;
    metadata_tag *mtag;

    /*  1.get metadata tag for next packet in in_buffer, delete tag or move tag later on
        2.copy packet worth of data from inbuffer to intermediate buffer
        3.update rx_frame count
        4.move or create metadata tag in intermedia buffer
        5.repeat until in_buffer is empty
    */

    // no input data, return
    if( cbuffer_calc_amount_data_ex(in_buffer) == 0 )
    {
        return CODEC_SUCCESS;
    }

    do
    {
        // look at next metadata tag and work out if enough space in intermediate buffer to store it
        mtag = buff_metadata_peek(in_buffer);

        L4_DBG_MSG1("LDAC ldac_decoder_stores_rx_data mtag length=%d ",mtag->length );

        // to meet the LDAC mandatory requirement for buffer burst overflow control, dispose of any data that exceeds 80% buffer full level
        // and replace with silence
#if defined LDAC_BURST_BUFFER_LEVEL_CONTROL
        if((mtag)&&((cbuffer_calc_amount_data_ex(cb_main) + mtag->length) < LDAC_RXBUF_BURST_CONTROL_LEVEL))
        {
#elif defined LDAC_BURST_FRAME_LEVEL_CONTROL
        if((mtag)&&(pDecParams->RxBuf.nFrame < LDAC_RXBUF_FRAME_CONTROL_LEVEL))
        {
#else
        {
#endif
            // Get amount of space in intermediate buffer
            space_octets = cbuffer_calc_amount_space_ex(cb_main);
            // check enough space to copy in next packet
            if(mtag->length < space_octets)
            {
                metadata_tag *new_mtag;

                // enough space to copy packet from input buffer to intermediate buffer
                read_octets = 0;

                L4_DBG_MSG2("LDAC ldac_decoder_stores_rx_data space ok: mtag length=%d space octets = %d",mtag->length, space_octets );

                // remove tag from input buffer
                new_mtag = buff_metadata_remove(in_buffer, mtag->length, &b4idx, &afteridx);

                // Read the payload header and get the LDAC frame number,
                // and then copy All payload data into cb_main by frame.
                reset_cbuffers(cb_work);
                read_octets += cbuffer_copy_ex(cb_work, in_buffer, 1);
                addr = cbuffer_get_read_address_ex(cb_work, &offset);
                payload_header = (int)*addr;
                nsft = 8 * (3 - offset); // offset must be 0, 1, 2 or 3.
                nFrmRx = (payload_header>>nsft) & 0xF;

                L4_DBG_MSG2("LDAC ldac_decoder_stores_rx_data no_frames=%d new_mtag = %x",nFrmRx, new_mtag );

                // validity check of tag and number of frames to decode
                if((new_mtag!=NULL)&&(nFrmRx>0)&&(nFrmRx<LDAC_MAX_FRAMES))
                {
                    L4_DBG_MSG2("LDAC ldac_decoder_stores_rx_data no_frames=%d , new_tag_length",nFrmRx, new_mtag->length );

                    // remove the 1 octet already read leaving 660 for 2dh5 frames
                    new_mtag->length -= 1;

                    // copy the rest of the packet minus the payload header to the main intermediate buffer
                    read_octets += cbuffer_copy_ex(cb_main, in_buffer, new_mtag->length);

                    // add the number of audio frames in this packet to the metadata tag private data
                    buff_metadata_add_private_data(new_mtag, META_PRIV_KEY_USER_DATA, sizeof(unsigned), &nFrmRx);

                    // check intermediate buffer has metadata
                    if (buff_has_metadata(cb_main))
                    {
                        L4_DBG_MSG3("LDAC cb_main buff_metadata_append size=%d read octets = %d ttp = %d",new_mtag->length, read_octets, new_mtag->timestamp );

                        // add to cb_main tags
                        buff_metadata_append(cb_main, new_mtag, 0, new_mtag->length);
                    }
                    // no metadata tags, need to enable and add one
                    else
                    {
                        metadata_tag *mtag_init;

                        if(buff_metadata_enable(cb_main)==NULL)
                        {
                            L2_DBG_MSG("LDAC cb_main buff_metadata_enable failed");
                        }
                        else
                        {
                            L4_DBG_MSG2("LDAC cb_main buff_metadata_append size=%d read octets = %d",new_mtag->length,read_octets );

                            mtag_init = buff_metadata_new_tag();

                            // add the number of audio frames in this packet to the metadata tag private data
                            buff_metadata_add_private_data(mtag_init, META_PRIV_KEY_USER_DATA, sizeof(unsigned), &nFrmRx);

                            if (mtag_init != NULL)
                            {
                                mtag_init->length = new_mtag->length;
                                mtag_init->flags = mtag->flags;
                                mtag_init->timestamp = mtag->timestamp;
                                mtag_init->sp_adjust = mtag->sp_adjust;
                                mtag_init->index = 0;
                                METADATA_PACKET_START_SET(mtag_init);
                                METADATA_PACKET_END_SET(mtag_init);
                            }
                            buff_metadata_append(cb_main, mtag_init, 0, new_mtag->length);
                        }
                        // delete old tag
                        buff_metadata_delete_tag(mtag,FALSE);
                    }
                    // update no of frames copied
                    (*nFrmRegistered) += nFrmRx;
                    L4_DBG_MSG1("LDAC store RxData: total  frames stored %d",*nFrmRegistered );


                }
                // number of frames is wrong or outside of upper limit, assume corrupted data and dispose of data/resync
                else
                {
                    L2_DBG_MSG1("LDAC store RxData: frame length wrong %d", nFrmRx);

                    // ditch input buffer contents and resync
                    rx_octets =  cbuffer_calc_amount_data_ex(in_buffer);
                    cbuffer_advance_read_ptr_ex(in_buffer, rx_octets);

                    // delete any current tags and resync
                    if(new_mtag)
                        buff_metadata_tag_list_delete(new_mtag);

                    return CODEC_ERROR;
                }
            }
            // if cb_main is full
            else
            {
               L4_DBG_MSG2("LDAC store RxData: cb_main full, space %d codec_in_buff = %d", space_octets,cbuffer_calc_amount_data_ex(in_buffer));
               return CODEC_SUCCESS;
            }

            hRxBuf->nFrame += nFrmRx;
        }
#if defined LDAC_BURST_BUFFER_LEVEL_CONTROL || defined LDAC_BURST_FRAME_LEVEL_CONTROL
        /* buffer level will exceed the 80% burst threshold if frame is added so discard frame of data, due to the descrepancy
           this will cause in the ttp value of the metadata tags, the source_sync operator will insert silence when this happens */
        else
        {
             // ensure tag is valid
             if(mtag && mtag->length)
             {
                 metadata_tag *new_mtag;
                 // remove tag from input buffer
                 new_mtag = buff_metadata_remove(in_buffer, mtag->length, &b4idx, &afteridx);
                 // dispose of data in input buffer
                 cbuffer_advance_read_ptr_ex(in_buffer, new_mtag->length);

                 L2_DBG_MSG1("LDAC ldac_decoder_stores_rx_data BURST DISCARD FRAMES %d",new_mtag->length );

             }
        }
#endif
    // repeat while still input data and intermediate buffer space
    }while((mtag != NULL) &&(cbuffer_calc_amount_data_ex(in_buffer) > 0)&&(cbuffer_calc_amount_space_ex(cb_main)>mtag->length));


    L4_DBG_MSG2("LDAC store RxData: codec_success stored %d total frames %d",*nFrmRegistered, hRxBuf->nFrame );

    //keep clone buffer pointers synced to main buffer as this is used for LDAC validity checking
    rxbuf_op_sync_clone(hRxBuf);

    return CODEC_SUCCESS;
}


void ldac_decoder_initiliase( LDAC_DEC_PARAMS *pDecParams )
{
    pDecParams->RxBuf.nFrame = 0;
    pDecParams->RxBuf.remaining_FrmNum = 0;
    pDecParams->RxBuf.carried_Octets = 0;
    pDecParams->playing=FALSE;
    reset_cbuffers(pDecParams->RxBuf.carried);
    reset_cbuffers(pDecParams->RxBuf.main);
    rxbuf_op_sync_clone(&pDecParams->RxBuf);
    reset_cbuffers(pDecParams->cb_stream);
}


int ldac_decoder_decode_frames( LDAC_DEC_PARAMS *pDecParams, unsigned char *p_pcm_out_0, unsigned char *p_pcm_out_1)
{
    LDAC_DEC_RX_BUF *hRxBuf = &pDecParams->RxBuf;
    tCbuffer *cb_stream = pDecParams->cb_stream; // buffer to pass bitstream to decoder
    int used_bytes, wrote_bytes;
    HANDLE_LDAC_BT hData;
    unsigned char *a_stream;
    int n_read_bytes;
    int result, return_mode;
    unsigned int *addr, offset;
    int error_code;
    uint32 frame_status;

    hData = pDecParams->hData;
    /* reset cbuffer read/write pointer */
    reset_cbuffers(cb_stream);

    
    return_mode = rxbuf_op_peek_frame_data( hRxBuf, cb_stream, &n_read_bytes, &frame_status);
    if (return_mode != CODEC_SUCCESS){ // no data in rx_buf
        if(return_mode == CODEC_ERROR){
            if(search_next_frame_header(hRxBuf,cb_stream,pDecParams->frame_size,pDecParams->sampling_freq,pDecParams->channel_mode)==CODEC_SUCCESS){
                rxbuf_op_peek_frame_data( hRxBuf, cb_stream, &n_read_bytes, &frame_status);
                goto NEXT_STEP;
            }
        }
        /*clear nFrame*/
        hRxBuf->nFrame = 0;

        return return_mode;
    }

NEXT_STEP:

    rxbuf_op_pop_frame_data(hRxBuf, n_read_bytes);/*discard frame*/

    addr = cbuffer_get_read_address_ex(cb_stream, &offset);
    a_stream = (unsigned char*)(addr + offset);

    L4_DBG_MSG4("ldacBT_decode_S32 data = %x %x %x %x",a_stream[0],a_stream[1],a_stream[2],a_stream[3]);

    result = ldacBT_decode_S32( hData, a_stream, p_pcm_out_0, p_pcm_out_1,n_read_bytes, &used_bytes, &wrote_bytes );
    if (result) {
        error_code = ldacBT_get_error_code(hData);
        L2_DBG_MSG1("ldacBT_get_error_code=0x%x",error_code);
        return_mode = CODEC_ERROR; //TODO: tentative value. must replace to correct one.
        return return_mode;
    }
    /*decode success*/
    return_mode = CODEC_SUCCESS;


    if((pDecParams->channel_mode==LDACBT_CHANNEL_MODE_STEREO)||(pDecParams->channel_mode==LDACBT_CHANNEL_MODE_DUAL_CHANNEL)){
        pDecParams->num_output_samples = wrote_bytes/2/4;/*32bit pcm*/
    }else{//MONO
        pDecParams->num_output_samples = wrote_bytes/4;/*32bit pcm*/
    }
        
    pDecParams->frame_size = used_bytes;
    return return_mode;
}

volatile char debug_stop_2 = 1;

// transistion metadata from codec in to intermediate rxbuf, packets are not yet decoded so will be encoded frame sized
void HandleInputBufferMetadata(LDAC_DEC_PARAMS *pDecParams, tCbuffer *in_buffer, int read_octets, tCbuffer *metadata_op_buffer)
{
            unsigned b4idx, afteridx;
            metadata_tag *mtag;
            metadata_tag *new_tag;
            unsigned avail;
            mtag = NULL;
            b4idx = 0;
            afteridx = 0;

            L4_DBG_MSG1("LDAC handle metadata read_octets = %d",read_octets);

            avail = buff_metadata_available_octets(in_buffer);
            if (avail < LDAC_MIN_PACKET_SIZE)
            {
                L2_DBG_MSG("LDAC mtag fail, no data left");
            }
            else
                L4_DBG_MSG1("LDAC mtag ok, input buffer level octets = %d",avail);

            // remove tag from input buffer
            L4_DBG_MSG4("LDAC buff_metadata_remove size=%d b4idx=%d afteridx=%d avail=%d", (read_octets+1), b4idx, afteridx,avail);
            mtag = buff_metadata_remove(in_buffer, read_octets, &b4idx, &afteridx);

            // move tag to intermediate buffer rxbuf.main
            if (buff_has_metadata(metadata_op_buffer))
            {
                unsigned after_octets = read_octets;

                // append tag to intermediate output buffer
                L4_DBG_MSG2("LDAC buff_metadata_append after_octets=%d ttp=%d", after_octets, mtag->timestamp);
                buff_metadata_append(metadata_op_buffer, mtag, 0, after_octets);
            }
            else
            {
                // no tags in output buffer yet so create a new one
                /* The first tag is allocated outside the for loop.*/
                if(mtag)
                {
                    // create new tag
                    new_tag = buff_metadata_new_tag();

                    // ensure new tag is created succesfully
                    if(new_tag)
                    {
                        // populate timestamp data etc
                        new_tag->length = read_octets;
                        new_tag->flags = mtag->flags;
                        new_tag->timestamp = mtag->timestamp;
                        new_tag->sp_adjust = mtag->sp_adjust;
                        new_tag->index = 0;

                        if(buff_metadata_enable(metadata_op_buffer)==NULL)
                        {
                            L2_DBG_MSG("LDAC buff_metadata_enable failed");
                        }
                        else
                        {
                            L2_DBG_MSG2("LDAC buff_metadata_append size=%d read octets = %d",new_tag->length,read_octets );

                            // add to tag list
                            buff_metadata_append(metadata_op_buffer, new_tag, 0, new_tag->length);
                        }
                    }

                    // delete old tag
                    buff_metadata_tag_list_delete(mtag);
                    L2_DBG_MSG("LDAC handle metadata, start new tag and delete mtag");
                }
            }
}

